/*****************************************************
** Author: 
** Date: 2020-07-10
*
*****************************************************/

#include <string.h>
#include "slink.h"
#include "comm.h"

static struct subdev subdev_pools[SUBDEV_NUM_MAX];
static struct subdev *p_used;
static struct subdev *p_free;

/**
 * @brief
 * @param  None
 * @retval None
 */
static void subdev_slink_dump(struct subdev *list, const char *str)
{
#if 1
    struct subdev *p;
    int i;
    tc_log("subdev dump %s %p", str, list);
    for (p = list, i = 0; p != NULL; p = p->next, i++) {
        tc_log("[%d] p %p next %p value %d", i, p, p->next, p->value);
    }
#endif
}

int subdev_comm_init(void)
{
	struct subdev *head = subdev_pools;
	int i;

	/* 1. init pools list */
	memset(subdev_pools, 0x0, sizeof(subdev_pools));

	for (i = 0; i < (SUBDEV_NUM_MAX - 1); ++i)
		head[i].next = &head[i+1];

	head[i].next = NULL;

	p_free = head;
	p_used = NULL;

	tc_log("&p_used %p p_used %p", &p_used, p_used);
	tc_log("&p_free %p p_free %p", &p_free, p_free);

	subdev_slink_dump(p_used, "p_used");
	subdev_slink_dump(p_free, "p_free");

    tc_log("subdev init done");
	return 0;
}

int subdve_comm_add(int value)
{
	if (p_free == NULL) {
        tc_log_err("subdev pool is full");
        return -1;
    }

    // TODO: lock

    struct subdev *new = p_free;
    p_free = new->next;

    new->value = value;

    new->next = p_used;
    p_used = new;

    // TODO: unlock

    return 0;
}

int subdev_comm_del(struct subdev *dev)
{
	struct subdev **pwalk = &p_used;

	tc_log("&pwalk %p pwalk %p *pwalk %p &((*pwalk)->next) %p", &pwalk, pwalk, *pwalk, &((*pwalk)->next));
	while ((*pwalk) != NULL && (void *)&((*pwalk)->next) != (void *)dev) {
		pwalk = &((*pwalk)->next);
		tc_log("&pwalk %p pwalk %p *pwalk %p &((*pwalk)->next) %p", &pwalk, pwalk, *pwalk, &((*pwalk)->next));
	}
	if ((*pwalk) == NULL)
        return -1;

	struct subdev *pdel = *pwalk;
    *pwalk = (*pwalk)->next;

    pdel->next = p_free;
    p_free = pdel;
    return 0;
}

void test(void)
{
	int i;

	subdev_comm_init();

	tc_log("try to add");
	for (i = 0; i < 3; ++i) {
		subdve_comm_add(i);

		subdev_slink_dump(p_used, "p_used");
		subdev_slink_dump(p_free, "p_free");
	}

#if 0
	tc_log("try to del");
	for (i = 0; i < 3; ++i) {
		subdev_comm_del(i);

		subdev_slink_dump(p_used, "p_used");
		subdev_slink_dump(p_free, "p_free");
	}
#else
	tc_log("&subdev_pools[0] %p", &subdev_pools[0]);
	subdev_comm_del(&subdev_pools[0]);

	subdev_slink_dump(p_used, "p_used");
	subdev_slink_dump(p_free, "p_free");
#endif
}

/* End of file */



